#!/bin/bash
#	check-markit  4.2.1.1114  2020-12-22T21:01:38.222906-06:00 (CST)  https://github.com/BradleyA/markit.git  master  uadmin  three-rpi3b.cptx86.com 4.1.146-24-g68844ef  
#	   check-markit find-code.sh markit -->   release ready for production  
#86# check-markit - check file release with repository release
###  Production standard 5.3.559 Copyright                                    # 3.559
#    Copyright (c) 2020 Bradley Allen                                                # 3.555
#    MIT License is online in the repository as a file named LICENSE"         # 3.559
###  Production standard 3.0 shellcheck
###  Production standard 1.3.614 DEBUG variable
#    Order of precedence: environment variable, default code
if [[ "${DEBUG}" == ""  ]] ; then DEBUG="0" ; fi   # 0 = debug off, 1 = debug on, 'export DEBUG=1', 'unset DEBUG' to unset environment variable (bash)
if [[ "${DEBUG}" == "2" ]] ; then set -x    ; fi   # Print trace of simple commands before they are executed
if [[ "${DEBUG}" == "3" ]] ; then set -v    ; fi   # Print shell input lines as they are read
if [[ "${DEBUG}" == "4" ]] ; then set -e    ; fi   # Exit immediately if non-zero exit status
if [[ "${DEBUG}" == "5" ]] ; then set -e -o pipefail ; fi   # Exit immediately if non-zero exit status and exit if any command in a pipeline errors
#
BOLD=$(tput -Txterm bold)
UNDERLINE=$(tput -Txterm sgr 0 1)  # 0.3.583
NORMAL=$(tput -Txterm sgr0)
RED=$(tput    setaf 1)
YELLOW=$(tput setaf 3)
BLUE=$(tput   setaf 4)
PURPLE=$(tput setaf 5)
CYAN=$(tput   setaf 6)
WHITE=$(tput  setaf 7)

###  Production standard 7.0 Default variable value
FILE_NAME=""
MARKIT_FILE=""
TMP_MARKIT_DIR=$(mktemp --directory /tmp/TMP_MARKIT_DIRXXXXXX)   # Create a temporary directory

###  Production standard 8.3.541 --usage
COMMAND_NAME=$(echo "${0}" | sed 's/^.*\///')                                               # 3.541
display_usage() {
echo -e "\n${NORMAL}${COMMAND_NAME}\n   check file release with repository release"
echo -e "\n${BOLD}USAGE${NORMAL}"
echo    "   ${COMMAND_NAME} <FILE_NAME>"
echo -e "   ${COMMAND_NAME} [--filename <PATH>/<FILE_NAME> | -f <PATH>/<FILE_NAME>]\n"
echo    "   ${COMMAND_NAME} [--help | -help | help | -h | h | -?]"
echo    "   ${COMMAND_NAME} [--usage | -usage | -u]"
echo    "   ${COMMAND_NAME} [--version | -version | -v]"
}

###  Production standard 0.3.615 --help
display_help() {
display_usage
#    Displaying help DESCRIPTION in English en_US.UTF-8, en.UTF-8, C.UTF-8                  # 3.550
echo -e "\n${BOLD}DESCRIPTION${NORMAL}"
echo    "Check the release of a file that was marked using markit with the GitHub"
echo    "repository or Bitbucket repository or GitLab project release.  Check-markit may"
echo    "require --filename option to include the relative or absolute path with the"
echo    "file name."
echo -e "\nCheck-markit only works on files that are marked after 2018-02-27."
echo -e "\nCheck-markit only works with markit files that used the https:// URLs for"
echo    "GitHub, Bitbucket, and GitLab repositories.  Check-markit does not currently"
echo    "support files with SSH URLs for GitHub, Bitbucket, and GitLab repositories."

###  Production standard 4.3.587 Documentation Language                                     # 3.550
#    Displaying help DESCRIPTION in French fr_CA.UTF-8, fr_FR.UTF-8, fr_CH.UTF-8
if [[ "${LANG}" == "fr_CA.UTF-8" ]] || [[ "${LANG}" == "fr_FR.UTF-8" ]] || [[ "${LANG}" == "fr_CH.UTF-8" ]] ; then
  echo -e "\n--> ${LANG}"
  echo    "<Votre aide va ici>" # Your help goes here
  echo    "Souhaitez-vous traduire la section description?" # Would you like to translate the description section?
elif ! [[ "${LANG}" == "en_US.UTF-8" ||  "${LANG}" == "en.UTF-8" || "${LANG}" == "C.UTF-8" ]] ; then  # 3.550
  new_message "${LINENO}" "${YELLOW}INFO${WHITE}" "  Your language, ${LANG}, is not supported.  Would you like to translate the description section?" 1>&2
fi

echo -e "\n${BOLD}ENVIRONMENT VARIABLES${NORMAL}"
echo    "If using the bash shell, enter; 'export DEBUG=1' on the command line to set"
echo    "the environment variable DEBUG to '1' (0 = debug off, 1 = debug on).  Use the"
echo    "command, 'unset DEBUG' to remove the exported information from the environment"
echo    "variable DEBUG.  You are on your own defining environment variables if"
echo    "you are using other shells."

###  Production standard 1.3.614 DEBUG variable
echo    "   DEBUG           (default off '0')  The DEBUG environment variable can be set"   # 3.550
echo    "                   to 0, 1, 2, 3, 4 or 5.  The setting '' or 0 will turn off"      # 3.550
echo    "                   all DEBUG messages during execution of this script.  The"       # 3.550
echo    "                   setting 1 will print all DEBUG messages during execution."      # 3.550
echo    "                   Setting 2 (set -x) will print a trace of simple commands"       # 3.550
echo    "                   before they are executed.  Setting 3 (set -v) will print"       # 3.550
echo    "                   shell input lines as they are read.  Setting 4 (set -e) will"   # 3.550
echo    "                   exit immediately if non-zero exit status is recieved with"      # 3.550
echo    "                   some exceptions.  Setting 5 (set -e -o pipefail) will do"       # 3.550
echo    "                   setting 4 and exit if any command in a pipeline errors.  For"   # 3.550
echo    "                   more information about the set options, see man bash."          # 3.550

echo -e "\n${BOLD}OPTIONS${NORMAL}"
echo -e "Order of precedence: CLI options, environment variable, default value.\n"                     # 0.3.595
echo    "   --help, -help, help, -h, h, -?"                                                            # 0.3.595
echo -e "\tOn-line brief reference manual\n"                                                           # 0.3.595
echo    "   --usage, -usage, -u"                                                                       # 0.3.595
echo -e "\tOn-line command usage\n"                                                                    # 0.3.595
echo    "   --version, -version, -v"                                                                   # 0.3.595
echo -e "\tOn-line command version\n"                                                                  # 0.3.595
#
echo    "   --filename <PATH>/<FILE_NAME>, -f"
echo -e "\tInclude the relative or absolute path with the file name"

echo -e "\n${BOLD}DOCUMENTATION${NORMAL}"
echo    "  ${UNDERLINE}https://github.com/BradleyA/markit/blob/master/README.md${NORMAL}"    # 0.3.583

echo -e "\n${BOLD}EXAMPLES${NORMAL}"
echo -e "   Check file named sample.c release in relative path testfile/ with\n   repository release."  # 0.3.550
echo -e "\t${BOLD}${COMMAND_NAME} -f testfiles/sample.c${NORMAL}\n"                                     # 0.3.550
echo    "   Check file named markit release with repository release."                                   # 0.3.550
echo -e "\t${BOLD}${COMMAND_NAME} markit${NORMAL}"                                                      # 0.3.550

echo -e "\n${BOLD}SEE ALSO${NORMAL}"                                                                          #  0.3.615
echo    "   ${BOLD}markit${NORMAL}  Mark tracked modified file(s), in your local"                             #  0.3.615
echo -e "\tGit repository and push those changes to a remote Git repository"                                  #  0.3.615
echo -e "\t(${UNDERLINE}https://github.com/BradleyA/markit/blob/master/README.md${NORMAL})\n"                 #  0.3.615
echo    "   ${BOLD}find-code.sh${NORMAL}  Search each system found in"                                        #  0.3.615
echo -e "\t<DATA_DIR>/<SYSTEMS_FILE> file for .git repositories in ~/.. directories"                          #  0.3.615
echo -e "\t(${UNDERLINE}https://github.com/BradleyA/markit/blob/master/README.md#usage-find-codesh${NORMAL})\n"  #  0.3.615

echo -e "\n${BOLD}AUTHOR${NORMAL}"                                                          # 3.550
echo    "   ${COMMAND_NAME} was written by Bradley Allen <allen.bradley@ymail.com>"         # 3.550

echo -e "\n${BOLD}REPORTING BUGS${NORMAL}"                                                  # 3.550
echo    "   Report ${COMMAND_NAME} bugs ${UNDERLINE}https://github.com/BradleyA/markit/issues/new/choose${NORMAL}"         # 0.3.583

###  Production standard 5.3.559 Copyright                                            # 3.559
echo -e "\n${BOLD}COPYRIGHT${NORMAL}"                                                       # 3.550
echo    "   Copyright (c) 2020 Bradley Allen"                                               # 3.550
echo    "   MIT License is online in the repository as a file named LICENSE"          # 3.559
}

#    Date and time function ISO 8601
get_date_stamp() {
  DATE_STAMP=$(date +%Y-%m-%dT%H:%M:%S.%6N%:z)
  TEMP=$(date +%Z)
  DATE_STAMP="${DATE_STAMP} (${TEMP})"
}

#    Fully qualified domain name FQDN hostname
LOCALHOST=$(hostname -f)

#    Version
#    Assumptions for the next two lines of code:  The second line in this script includes the script path & name as the second item and
#    the script version as the third item separated with space(s).  The tool I use is called 'markit'. See example line below:
#       template/template.sh  3.517.783  2019-09-13T18:20:42.144356-05:00 (CDT)  https://github.com/BradleyA/user-files.git  uadmin  one-rpi3b.cptx86.com 3.516  
SCRIPT_NAME=$(head -2 "${0}" | awk '{printf $2}')  #  Different from ${COMMAND_NAME}=$(echo "${0}" | sed 's/^.*\///'), SCRIPT_NAME = includes Git repository directory and can be used any where in script (for dev, test teams)
SCRIPT_VERSION=$(head -2 "${0}" | awk '{printf $3}')
if [[ "${SCRIPT_NAME}" == "" ]] ; then SCRIPT_NAME="${0}" ; fi
if [[ "${SCRIPT_VERSION}" == "" ]] ; then SCRIPT_VERSION="v?.?" ; fi

#    GID
GROUP_ID=$(id -g)

###  Production standard 2.3.614 Log format (WHEN WHERE WHAT Version Line WHO UID:GID [TYPE] Message)
new_message() {  #  $1="${LINENO}"  $2="DEBUG INFO ERROR WARN"  $3="message"
  get_date_stamp
  echo -e "${NORMAL}${DATE_STAMP} ${LOCALHOST} ${BOLD}${CYAN}${SCRIPT_NAME}${NORMAL}[$$] ${BOLD}${BLUE}${SCRIPT_VERSION} ${PURPLE}${1}${NORMAL} ${USER} ${UID}:${GROUP_ID} ${BOLD}[${2}]${NORMAL}  ${3}"  # 2.3.614
}

#    INFO
if [[ "${DEBUG}" == "1" ]] ; then new_message "${LINENO}" "${YELLOW}INFO${WHITE}" "${BOLD}${CYAN}  Started...${NORMAL}" 1>&2 ; fi  # 1.3.614

#    Added following code because USER is not defined in crobtab jobs
if ! [[ "${USER}" == "${LOGNAME}" ]] ; then  USER=${LOGNAME} ; fi
if [[ "${DEBUG}" == "1" ]] ; then new_message "${LINENO}" "${YELLOW}DEBUG${WHITE}" "  Setting USER to support crobtab...  USER >${YELLOW}${USER}${WHITE}<  LOGNAME >${YELLOW}${LOGNAME}${WHITE}<" 1>&2 ; fi  # 1.3.614

#    DEBUG  # 1.3.614
if [[ "${DEBUG}" == "1" ]] ; then new_message "${LINENO}" "${YELLOW}DEBUG${WHITE}" "  Name_of_command >${YELLOW}${SCRIPT_NAME}${WHITE}< Name_of_arg1 >${YELLOW}${1}${WHITE}< Name_of_arg2 >${YELLOW}${2}${WHITE}< Name_of_arg3 >${YELLOW}${3}${WHITE}<  Version of bash ${YELLOW}${BASH_VERSION}${WHITE}" 1>&2 ; fi  # 1.3.614

###  Production standard 9.3.606 Parse CLI options and arguments
while [[ "${#}" -gt 0 ]] ; do
  case "${1}" in
    --help|-help|help|-h|h|-\?)  display_help | more ; exit 0 ;;
    --usage|-usage|usage|-u)  display_usage ; exit 0  ;;
    --version|-version|version|-v)  echo "${SCRIPT_NAME} ${SCRIPT_VERSION}" ; exit 0  ;;
#
    -f|--filename)  if [[ "${2}" == "" ]] ; then echo -e "\n${BOLD}    Argument for ${YELLOW}${1}${WHITE} is not found on command line.${NORMAL}\n" ; exit 1 ; fi ; MARKIT_FILE=${2} ; shift 2 ;;  # 9.3.605
    -f=*|--filename=*)  MARKIT_FILE="${1#*=}" ; if [[ "${MARKIT_FILE}" == "" ]] ; then echo -e "\n${BOLD}    Argument for ${YELLOW}${1}${WHITE} is not found on command line.${NORMAL}\n" ; exit 1 ; fi ; shift  ;;  # 9.3.605
#    *) echo -e "\n${BOLD}    Invalid option, ${YELLOW}${1}${WHITE}, try ${YELLOW}--usage${NORMAL}\n" ; exit 1 ; ;; # 9.3.606
    *)  break ;; # 9.3.607
  esac
done
if [[ "${DEBUG}" == "1" ]] ; then new_message "${LINENO}" "${YELLOW}DEBUG${WHITE}" "  Variable... MARKIT_FILE >${BOLD}${CYAN}${MARKIT_FILE}${NORMAL}<" 1>&2 ; fi  # 1.3.614

###

###  Check if argument 1 is blank
if [[ "${1}" == "" ]] && [[ "${MARKIT_FILE}" == "" ]] ; then
  display_usage
  new_message "${LINENO}" "${RED}ERROR${WHITE}" "  File not found on command line" 1>&2
  exit 1
fi

#    Check if argument 1 is found on system
if [[ "${MARKIT_FILE}" == "" ]] ; then
  #    check if first character is a '-'
  if [[ "${1:0:1}"  == "-" ]] ; then echo -e "\n${BOLD}    Invalid option, ${YELLOW}${1}${WHITE}, try ${YELLOW}--usage${NORMAL}\n" ; exit 1 ; fi
  #    Locate file in the PATH
  TEMP=$(whereis "${1}")
  MARKIT_FILE=$(echo "${TEMP}" | awk '{print $2}' )
  if [[ "${DEBUG}" == "1" ]] ; then new_message "${LINENO}" "${YELLOW}DEBUG${WHITE}" "  Locate file in the PATH... MARKIT_FILE >${BOLD}${CYAN}${MARKIT_FILE}${NORMAL}<" 1>&2 ; fi  # 1.3.614
  #    Check if MARKIT_FILE is blank, not found on system
  if [[ "${MARKIT_FILE}" == "" ]] ; then
    new_message "${LINENO}" "${RED}ERROR${WHITE}" "  ${1} not found; use --file <path>/<file_name> or -f <path>/<file_name> option" 1>&2
    display_usage
    exit 1
  fi
fi

#    Parse file FILE_NAME from MARKIT_FILE
FILE_NAME=$(echo "${MARKIT_FILE}" | sed 's/.*\///')
#    Check if file exists and has a size greater than zero || if file exists and is readable
if [[ ! -s "${MARKIT_FILE}" ]] || [[ ! -r "${MARKIT_FILE}" ]] ; then
  new_message "${LINENO}" "${RED}ERROR${WHITE}" "  ${MARKIT_FILE} file is not found or is empty or is not readable" 1>&2
  exit 1
fi
REPOSITORY_COMMAND=$(grep git "${MARKIT_FILE}" | grep -m 1 "${FILE_NAME}" | awk '{print $6}' | sed 's/\.git$//')
MARKIT_FILE_RELEASE=$(grep git "${MARKIT_FILE}" | grep -m 1 "${FILE_NAME}" | awk '{print $3}')
MARKIT_FILE_DATE=$(grep git "${MARKIT_FILE}" | grep -m 1 "${FILE_NAME}" | awk '{print $4}')
#
if [[ "${DEBUG}" == "1" ]] ; then new_message "${LINENO}" "${YELLOW}DEBUG${WHITE}" "  MARKIT_FILE >${BOLD}${CYAN}${MARKIT_FILE}${NORMAL}< FILE_NAME >${BOLD}${CYAN}${FILE_NAME}${NORMAL}< REPOSITORY_COMMAND >${BOLD}${CYAN}${REPOSITORY_COMMAND}${NORMAL}< MARKIT_FILE_RELEASE >${BOLD}${CYAN}${MARKIT_FILE_RELEASE}${NORMAL}<" 1>&2 ; fi  # 1.3.614

#    Check file to determine if it was marked before markit release 3.10.142 2018-02-27.
if ! grep -q "https" <<< ${REPOSITORY_COMMAND}  ; then
  new_message "${LINENO}" "${RED}ERROR${WHITE}" "  ${MARKIT_FILE} is not marked with markit or the --file option was not used or git origin did not include https address (git remote -v) when marked or file was marked after 2018-02-27." 1>&2
  exit 1
fi

### >>>
#	need to make sure that script is able to contact GitHib or Bitbucket or GitLab before using curl
#	add a test
### >>>
###	Determine name of repository
if grep -q "github" <<< ${REPOSITORY_COMMAND} ; then
  if [[ "${DEBUG}" == "1" ]] ; then new_message "${LINENO}" "${YELLOW}DEBUG${WHITE}" "  Checking GitHub for ${BOLD}${CYAN}${FILE_NAME}${NORMAL} repository release information" 1>&2 ; fi  # 1.3.614
  REPOSITORY_COMMAND=$(echo "${REPOSITORY_COMMAND}" | sed 's/github.com/api.github.com\/repos/')
  REPOSITORY_COMMAND="curl \-L ${REPOSITORY_COMMAND}/tarball | tar --directory ${TMP_MARKIT_DIR} -xzf - "
  if [[ "${DEBUG}" == "1" ]] ; then new_message "${LINENO}" "${YELLOW}DEBUG${WHITE}" "  REPOSITORY_COMMAND >${BOLD}${CYAN}${REPOSITORY_COMMAND}${NORMAL}<" 1>&2 ; fi  # 1.3.614
elif grep -q "gitlab" <<< ${REPOSITORY_COMMAND} ; then
  if [[ "${DEBUG}" == "1" ]] ; then new_message "${LINENO}" "${YELLOW}DEBUG${WHITE}" "  Checking GitLab for ${BOLD}${FILE_NAME}${NORMAL} repository release information" 1>&2 ; fi  # 1.3.614
  REPOSITORY_PROJECT_NAME=$(echo "${REPOSITORY_COMMAND}" | sed 's/^https:\/\/.*\/.*\///' | sed 's/\.git$//')
  REPOSITORY_COMMAND=$(echo "${REPOSITORY_COMMAND}" | sed 's/\.git$/\/-\/archive\/master\//')
  if [[ "${DEBUG}" == "1" ]] ; then new_message "${LINENO}" "${YELLOW}DEBUG${WHITE}" "  MARKIT_FILE >${BOLD}${CYAN}${MARKIT_FILE}${NORMAL}< FILE_NAME >${BOLD}${CYAN}${FILE_NAME}${NORMAL}< REPOSITORY_COMMAND >${BOLD}${CYAN}${REPOSITORY_COMMAND}${NORMAL}< MARKIT_FILE_RELEASE >${BOLD}${CYAN}${MARKIT_FILE_RELEASE}${NORMAL}<" 1>&2 ; fi  # 1.3.614
  REPOSITORY_COMMAND="curl \-L ${REPOSITORY_COMMAND}${REPOSITORY_PROJECT_NAME}-master.tar.gz | tar --directory ${TMP_MARKIT_DIR} -xzf - "
elif grep -q "bitbucket" <<< ${REPOSITORY_COMMAND} ; then
  if [[ "${DEBUG}" == "1" ]] ; then new_message "${LINENO}" "${YELLOW}DEBUG${WHITE}" "  Checking Bitbucket for ${BOLD}${FILE_NAME}${NORMAL} repository release information" 1>&2 ; fi  # 1.3.614
  REPOSITORY_COMMAND=$(echo "${REPOSITORY_COMMAND}" | sed 's/\/\/.*@/\/\//')
  REPOSITORY_COMMAND=$(echo "curl \-L ${REPOSITORY_COMMAND}/get/master.zip -o ${TMP_MARKIT_DIR}/master.zip ; unzip -qq ${TMP_MARKIT_DIR}/master.zip -d ${TMP_MARKIT_DIR}/")
  if [[ "${DEBUG}" == "1" ]] ; then new_message "${LINENO}" "${YELLOW}DEBUG${WHITE}" "  REPOSITORY_COMMAND >${BOLD}${CYAN}${REPOSITORY_COMMAND}${NORMAL}<" 1>&2 ; fi  # 1.3.614
else 
  if [[ "${DEBUG}" == "1" ]] ; then new_message "${LINENO}" "${YELLOW}DEBUG${WHITE}" "  MARKIT_FILE >${BOLD}${CYAN}${MARKIT_FILE}${NORMAL}< FILE_NAME >${BOLD}${CYAN}${FILE_NAME}${NORMAL}< REPOSITORY_COMMAND >${BOLD}${CYAN}${REPOSITORY_COMMAND}${NORMAL}< MARKIT_FILE_RELEASE >${BOLD}${CYAN}${MARKIT_FILE_RELEASE}${NORMAL}<" 1>&2 ; fi  # 1.3.614
  new_message "${LINENO}" "${RED}ERROR${WHITE}" "  Repository using SSH URLs or other repository like bitbucket, Codebase, Assembla, Fog Creek Kiln, etc." 1>&2
  exit 1
fi
###
if [[ "${DEBUG}" == "1" ]] ; then new_message "${LINENO}" "${YELLOW}DEBUG${WHITE}" "  MARKIT_FILE >${BOLD}${CYAN}${MARKIT_FILE}${NORMAL}< FILE_NAME >${BOLD}${CYAN}${FILE_NAME}${NORMAL}< REPOSITORY_COMMAND >${BOLD}${CYAN}${REPOSITORY_COMMAND}${NORMAL}< MARKIT_FILE_RELEASE >${BOLD}${CYAN}${MARKIT_FILE_RELEASE}${NORMAL}<" 1>&2 ; fi  # 1.3.614
#
eval "${REPOSITORY_COMMAND}"
REPOSITORY_FILE_NAME_LOCATION=$(find "${TMP_MARKIT_DIR}" -type f -name "${FILE_NAME}" -print)
REPOSITORY_MARKIT_FILE_RELEASE=$(grep git "${REPOSITORY_FILE_NAME_LOCATION}" | grep -m 1 "${FILE_NAME}" | awk '{print $3}')
REPOSITORY_MARKIT_FILE_DATE=$(grep git "${REPOSITORY_FILE_NAME_LOCATION}" | grep -m 1 "${FILE_NAME}" | awk '{print $4}')
cp -f "${REPOSITORY_FILE_NAME_LOCATION}" /tmp/"${FILE_NAME}"
rm -rf "${TMP_MARKIT_DIR}"
###
echo -e "\n  ${BOLD}${CYAN}${MARKIT_FILE}${NORMAL} release ${BOLD}${YELLOW}${MARKIT_FILE_RELEASE}${NORMAL}, commit date ${MARKIT_FILE_DATE}" 1>&2
echo -e "\n  ${BOLD}${CYAN}${FILE_NAME}${NORMAL} repository release ${BOLD}${YELLOW}${REPOSITORY_MARKIT_FILE_RELEASE}${NORMAL}, commit date ${REPOSITORY_MARKIT_FILE_DATE}\n" 1>&2
echo    "Repository copy placed in /tmp/${FILE_NAME}"

#
new_message "${LINENO}" "${YELLOW}INFO${WHITE}" "${BOLD}${CYAN}  Operation finished...${NORMAL}" 1>&2  # 1.3.614
###
